package com.sc.nft.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.MallOrderDao;
import com.sc.nft.dao.MallOrderProductDao;
import com.sc.nft.dao.MallUserPropsRewardsDao;
import com.sc.nft.dao.MallUserPropsRewardsDetailDao;
import com.sc.nft.entity.EquityProps;
import com.sc.nft.entity.MallActivitySpecs;
import com.sc.nft.entity.MallDrawActivityPrizePoolDetail;
import com.sc.nft.entity.MallOrder;
import com.sc.nft.entity.MallOrderProduct;
import com.sc.nft.entity.MallOrderStatusLog;
import com.sc.nft.entity.MallUserPropsRewards;
import com.sc.nft.entity.MallUserPropsRewardsDetail;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.vo.UserPropsRewardsDetailVO;
import com.sc.nft.enums.MallOrderStatusEnum;
import com.sc.nft.enums.props.reward.RewardDetailStatusEnum;
import com.sc.nft.service.EquityPropsService;
import com.sc.nft.service.MallActivitySpecsService;
import com.sc.nft.service.MallOrderStatusLogService;
import com.sc.nft.service.MallUserPropsRewardsDetailService;
import com.sc.nft.service.UserInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class MallUserPropsRewardsDetailServiceImpl implements MallUserPropsRewardsDetailService {

    private final MallUserPropsRewardsDetailDao mallUserPropsRewardsDetailDao;
    private final UserInfoService userInfoService;
    private final MallOrderProductDao mallOrderProductDao;
    private final MallOrderDao mallOrderDao;
    private final MallOrderStatusLogService mallOrderStatusLogService;
    private final EquityPropsService equityPropsService;
    private final MallUserPropsRewardsDao mallUserPropsRewardsDao;

    private final MallActivitySpecsService mallActivitySpecsService;


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void payScuuess(Long userId, Long daoId, List<MallOrderProduct> orderProdcutList, BigDecimal payAmount, String orderNo, Integer totalNum) {
        for (MallOrderProduct mallOrderProduct : orderProdcutList) {
            MallActivitySpecs mallActivitySpecs = mallActivitySpecsService.getByIdWithoutDeleted(mallOrderProduct.getActivitySpecsId());
            if (mallActivitySpecs.getPropsId() == null || mallActivitySpecs.getPropsRewardNum() == null) {
                continue;
            }
            LambdaQueryWrapper<MallUserPropsRewards> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MallUserPropsRewards::getUserId, userId);
            wrapper.eq(MallUserPropsRewards::getPropsId, mallActivitySpecs.getPropsId());
            MallUserPropsRewards mallUserPropsRewards = mallUserPropsRewardsDao.getOne(wrapper);
            if (mallUserPropsRewards == null) {
                mallUserPropsRewards = new MallUserPropsRewards();
                mallUserPropsRewards.setPropsId(mallActivitySpecs.getPropsId());
                mallUserPropsRewards.setUserId(userId);
                mallUserPropsRewards.setDaoId(daoId);
                mallUserPropsRewards.setPendingNum(mallActivitySpecs.getPropsRewardNum() * totalNum);
                mallUserPropsRewards.setPendingConsumptionAmount(payAmount);
            } else {
                mallUserPropsRewards.setPendingNum(mallUserPropsRewards.getPendingNum() + (mallActivitySpecs.getPropsRewardNum() * totalNum));
                mallUserPropsRewards.setPendingConsumptionAmount(mallUserPropsRewards.getPendingConsumptionAmount().add(payAmount));
            }
            mallUserPropsRewardsDao.saveOrUpdate(mallUserPropsRewards);
            MallUserPropsRewardsDetail mallUserPropsRewardsDetail = new MallUserPropsRewardsDetail();
            mallUserPropsRewardsDetail.setPropsId(mallActivitySpecs.getPropsId());
            mallUserPropsRewardsDetail.setDaoId(daoId);
            mallUserPropsRewardsDetail.setUserId(userId);
            mallUserPropsRewardsDetail.setPropsRewardsNum(mallActivitySpecs.getPropsRewardNum() * totalNum);
            mallUserPropsRewardsDetail.setOrderNo(orderNo);
            mallUserPropsRewardsDetail.setOrderId(mallOrderProduct.getMallOrderId());
            mallUserPropsRewardsDetail.setProductId(mallOrderProduct.getProductId());
            mallUserPropsRewardsDetail.setStatus(RewardDetailStatusEnum.PENDING);
            mallUserPropsRewardsDetail.setConsumptionAmount(payAmount);
            mallUserPropsRewardsDetailDao.save(mallUserPropsRewardsDetail);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void cancel(Long orderId, BigDecimal totalRefundSuccessAmount) {
        LambdaQueryWrapper<MallUserPropsRewardsDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MallUserPropsRewardsDetail::getOrderId, orderId);
        MallUserPropsRewardsDetail mallUserPropsRewardsDetail = mallUserPropsRewardsDetailDao.getOne(wrapper);
        if (mallUserPropsRewardsDetail == null) {
            return;
        }
        //更新汇总表
        LambdaQueryWrapper<MallUserPropsRewards> propsRewardsWrapper = new LambdaQueryWrapper<>();
        propsRewardsWrapper.eq(MallUserPropsRewards::getUserId, mallUserPropsRewardsDetail.getUserId())
                .eq(MallUserPropsRewards::getPropsId, mallUserPropsRewardsDetail.getPropsId());

        MallUserPropsRewards existingRewards = mallUserPropsRewardsDao.getOne(propsRewardsWrapper);
        if (existingRewards == null) {
            return;
        }
        // 如果记录存在，累计数量
        existingRewards.setPendingNum(existingRewards.getPendingNum() - mallUserPropsRewardsDetail.getPropsRewardsNum());
        existingRewards.setPendingConsumptionAmount(existingRewards.getPendingConsumptionAmount().subtract(totalRefundSuccessAmount));
        mallUserPropsRewardsDao.updateById(existingRewards);

        //更新明细表状态
        LambdaUpdateWrapper<MallUserPropsRewardsDetail> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(MallUserPropsRewardsDetail::getOrderId, mallUserPropsRewardsDetail.getOrderId());
        updateWrapper.set(MallUserPropsRewardsDetail::getStatus, RewardDetailStatusEnum.EXPIRED.getCode());
        mallUserPropsRewardsDetailDao.update(updateWrapper);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void confirm(Long orderId, BigDecimal consumptionAmount) {
        LambdaQueryWrapper<MallUserPropsRewardsDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MallUserPropsRewardsDetail::getOrderId, orderId);
        MallUserPropsRewardsDetail mallUserPropsRewardsDetail = mallUserPropsRewardsDetailDao.getOne(wrapper);
        if (mallUserPropsRewardsDetail == null) {
            return;
        }
        //更新汇总表
        LambdaQueryWrapper<MallUserPropsRewards> propsRewardsWrapper = new LambdaQueryWrapper<>();
        propsRewardsWrapper.eq(MallUserPropsRewards::getUserId, mallUserPropsRewardsDetail.getUserId())
                .eq(MallUserPropsRewards::getPropsId, mallUserPropsRewardsDetail.getPropsId());

        MallUserPropsRewards existingRewards = mallUserPropsRewardsDao.getOne(propsRewardsWrapper);
        if (existingRewards == null) {
            return;
        }
        LambdaUpdateWrapper<MallUserPropsRewards> updatePropsRewardsWrapper = new LambdaUpdateWrapper<>();
        updatePropsRewardsWrapper.eq(MallUserPropsRewards::getId, existingRewards.getId());
        updatePropsRewardsWrapper.setSql("pending_num = pending_num - " + mallUserPropsRewardsDetail.getPropsRewardsNum() +
                " , pending_consumption_amount = pending_consumption_amount - " + consumptionAmount +
                " , credited_num = credited_num + " + mallUserPropsRewardsDetail.getPropsRewardsNum() +
                " , credited_consumption_amount = credited_consumption_amount + " + consumptionAmount);
        mallUserPropsRewardsDao.update(updatePropsRewardsWrapper);

        //更新明细表状态
        LambdaUpdateWrapper<MallUserPropsRewardsDetail> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(MallUserPropsRewardsDetail::getOrderId, mallUserPropsRewardsDetail.getOrderId());
        updateWrapper.set(MallUserPropsRewardsDetail::getStatus, RewardDetailStatusEnum.CREDITED.getCode());
        mallUserPropsRewardsDetailDao.update(updateWrapper);
    }

    @Override
    public Page<UserPropsRewardsDetailVO> page(Long daoId, UserInfo user, Page page) {
        return this.page(daoId, user, null, null, null, null, null, page);
    }

    @Override
    public Page<UserPropsRewardsDetailVO> page(Date startTime, Date endTime, String phoneNumber,
                                               String orderNo, RewardDetailStatusEnum status, Page page) {
        return this.page(null, null, startTime, endTime, phoneNumber, orderNo, status, page);
    }

    public Page<UserPropsRewardsDetailVO> page(Long daoId, UserInfo user, Date startTime, Date endTime, String phoneNumber,
                                               String orderNo, RewardDetailStatusEnum status, Page page) {
        // 获取用户ID
        Long userId = null;
        if (user != null) {
            userId = user.getId();
        }
        if (StringUtils.isNotBlank(phoneNumber)) {
            UserInfo userInfo = userInfoService.getByUserTel(phoneNumber);
            if (userInfo != null) {
                userId = userInfo.getId();
            }
        }

        // 构建查询条件
        LambdaQueryWrapper<MallUserPropsRewardsDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(startTime != null, MallUserPropsRewardsDetail::getCreateTime, startTime)
                .le(endTime != null, MallUserPropsRewardsDetail::getCreateTime, endTime)
                .eq(userId != null, MallUserPropsRewardsDetail::getUserId, userId)
                .eq(daoId != null, MallUserPropsRewardsDetail::getDaoId, daoId)
                .eq(StringUtils.isNotBlank(orderNo), MallUserPropsRewardsDetail::getOrderNo, orderNo)
                .eq(status != null, MallUserPropsRewardsDetail::getStatus, status)
                .orderByDesc(MallUserPropsRewardsDetail::getCreateTime);

        // 执行分页查询
        Page<MallUserPropsRewardsDetail> detailPage = mallUserPropsRewardsDetailDao.page(page, wrapper);


        // 转换为VO对象
        Page<UserPropsRewardsDetailVO> voPage = new Page<>(detailPage.getCurrent(), detailPage.getSize(), detailPage.getTotal());
        voPage.setRecords(detailPage.getRecords().stream().map(this::convertToVO).collect(Collectors.toList()));
        return voPage;
    }

    private UserPropsRewardsDetailVO convertToVO(MallUserPropsRewardsDetail detail) {
        UserPropsRewardsDetailVO vo = new UserPropsRewardsDetailVO();
        BeanUtils.copyProperties(detail, vo);
        // 如果需要获取用户手机号
        UserInfo userInfo = userInfoService.getById(detail.getUserId());
        if (userInfo != null) {
            vo.setPhoneNumber(userInfo.getUserTel());
        }
        MallOrderProduct mallOrderProduct = mallOrderProductDao.getByOrderId(detail.getOrderId());
        if (mallOrderProduct != null) {
            vo.setProductName(mallOrderProduct.getProductName());
            vo.setProductNum(mallOrderProduct.getProductNum());
            vo.setProductSpecsName(mallOrderProduct.getProductSpecsName());
            vo.setThumbnail(mallOrderProduct.getThumbnail());
            vo.setOrderTime(mallOrderProduct.getCreateTime());
        }
        MallOrder mallOrder = mallOrderDao.getById(detail.getOrderId());
        if (mallOrder != null) {
            vo.setRealPrice(mallOrder.getRealPrice());
        }
        List<MallOrderStatusLog> mallOrderStatusLogList = mallOrderStatusLogService.getListByOrderId(detail.getOrderId());
        Map<String, MallOrderStatusLog> changeTypeToLogMap = mallOrderStatusLogList.stream()
                .collect(Collectors.toMap(
                        MallOrderStatusLog::getChangeType,
                        log -> log
                ));
        MallOrderStatusLog finishMallOrderStatusLog = changeTypeToLogMap.get(MallOrderStatusEnum.FINISH.toString());
        if (finishMallOrderStatusLog != null) {
            vo.setReceiveTime(finishMallOrderStatusLog.getCreateTime());
        }
        MallOrderStatusLog closureMallOrderStatusLog = changeTypeToLogMap.get(MallOrderStatusEnum.CLOSURE.toString());
        if (closureMallOrderStatusLog != null) {
            vo.setExpirationTime(closureMallOrderStatusLog.getCreateTime());
        }
        EquityProps equityProps = equityPropsService.getById(detail.getPropsId());
        if (equityProps != null) {
            vo.setPropsName(equityProps.getFirstTitle());
            vo.setCreationContent(equityProps.getCreationContent());
        }
        return vo;
    }
}
